package com.aliang.shopping.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.aliang.shopping.common.PageResult;
import com.aliang.shopping.common.Result;
import com.aliang.shopping.common.ResultCodeEnum;
import com.aliang.shopping.config.OssConfig;
import com.aliang.shopping.contact.ResultMsgContact;
import com.aliang.shopping.contact.SqlColumnConstant;
import com.aliang.shopping.exception.DataException;
import com.aliang.shopping.exception.ServiceException;
import com.aliang.shopping.log.annotation.OperateLog;
import com.aliang.shopping.log.enums.OperateType;
import com.aliang.shopping.model.converter.UserInfoConverter;
import com.aliang.shopping.model.dto.common.PageDTO;
import com.aliang.shopping.model.dto.common.UpdatePasswordDTO;
import com.aliang.shopping.model.dto.common.UpdateStatusDTO;
import com.aliang.shopping.model.dto.userInfo.UserInfoInsertDTO;
import com.aliang.shopping.model.dto.userInfo.UserInfoUpdateDTO;
import com.aliang.shopping.model.po.UserInfo;
import com.aliang.shopping.model.vo.UserInfoVO;
import com.aliang.shopping.security.PreventRepeatSubmit;
import com.aliang.shopping.service.UserInfoService;
import com.aliang.shopping.util.InputDataUtil;
import com.aliang.shopping.util.PasswordUtil;
import com.aliang.shopping.util.excel.ExcelUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/userInfo")
@AllArgsConstructor
public class UserInfoController {

    private final UserInfoService userInfoService;
    private final UserInfoConverter userInfoConverter;
    private final ExcelUtils excelUtils;
    private final OssConfig ossConfig;

    /**
     * 用户信息插入
     *
     * @param insertDTO
     * @return
     */
    @PostMapping("/insert")
    @ApiOperation("用户信息插入")
    @PreventRepeatSubmit
    @OperateLog(title = "用户信息插入", type = OperateType.INSERT)
    public Result<String> insertUserInfo(@RequestBody UserInfoInsertDTO insertDTO) {
        //用户名、密码非空校验
        if (StrUtil.hasBlank(insertDTO.getUsername(), insertDTO.getPassword())) {
            throw new DataException(ResultCodeEnum.DATA_LACK);
        }
        // 密码长度校验
        if (StrUtil.length(insertDTO.getPassword()) < 8) {
            throw new DataException(ResultCodeEnum.PASSWORD_LENGTH_ERR);
        }

        // 判断账号唯一
        int count = userInfoService.count(new QueryWrapper<UserInfo>().eq("username", insertDTO.getUsername()));
        if (count > 0) {
            throw new ServiceException(ResultCodeEnum.USERNAME_IS_EXIT);
        }
        //如果昵称未设置，设置为账号
        if (StrUtil.isBlank(insertDTO.getNickname())) {
            insertDTO.setNickname(insertDTO.getUsername());
        }
        //如果性别没设置，默认为男
        if (ObjectUtil.isNull(insertDTO.getSex())) {
            insertDTO.setSex(1);
        }
        // 密码加密
        insertDTO.setPassword(PasswordUtil.encrypt(insertDTO.getPassword()));
        // 如果有头像路径，需要截取
        if (StrUtil.isNotBlank(insertDTO.getAvatar())) {
            insertDTO.setAvatar(StrUtil.subAfter(insertDTO.getAvatar(), ossConfig.getUrl(), false));
        }
        //电话,邮箱不为空，需要验证唯一性
        if (StrUtil.isNotBlank(insertDTO.getPhone())) {
            this.userInfoService.checkPhoneUnique(insertDTO.getPhone());
        }
        if (StrUtil.isNotBlank(insertDTO.getEmail())) {
            this.userInfoService.checkEmailUnique(insertDTO.getEmail());
        }
        //转换数据
        UserInfo userInfo = this.userInfoConverter.toPoByInsertDTO(insertDTO);
        this.userInfoService.save(userInfo);
        return Result.ok(ResultMsgContact.REGISTER_SUCCESS);
    }

    /**
     * 用户信息删除
     *
     * @param ids
     * @return
     */
    @DeleteMapping("/del")
    @ApiOperation("用户信息删除")
    @PreventRepeatSubmit
    @OperateLog(title = "用户信息删除", type = OperateType.DELETE)
    public Result<String> delUserInfo(@RequestBody List<Long> ids) {
        this.userInfoService.removeByIds(ids);
        return Result.ok(ResultMsgContact.DELETE_SUCCESS);
    }

    /**
     * 用户信息更改
     *
     * @param updateDTO
     * @return
     */
    @PutMapping("/update")
    @ApiOperation("用户信息更改")
    @PreventRepeatSubmit
    @OperateLog(title = "用户信息更改", type = OperateType.UPDATE)
    public Result<String> updateUserInfo(@RequestBody UserInfoUpdateDTO updateDTO) {
        //必要字段校验
        if (ObjectUtil.isNull(updateDTO.getId())) {
            throw new DataException(ResultCodeEnum.DATA_LACK);
        }
        //电话,邮箱不为空，需要验证唯一性 todo 每次更新都要查，后续优化
        if (StrUtil.isNotBlank(updateDTO.getPhone())) {
            this.userInfoService.checkPhoneUnique(updateDTO.getPhone());
        }
        if (StrUtil.isNotBlank(updateDTO.getEmail())) {
            this.userInfoService.checkEmailUnique(updateDTO.getEmail());
        }
        // 如果有头像路径，需要截取
        if (StrUtil.isNotBlank(updateDTO.getAvatar())) {
            updateDTO.setAvatar(StrUtil.subAfter(updateDTO.getAvatar(), ossConfig.getUrl(), false));
        }
        //转换数据
        UserInfo userInfo = this.userInfoConverter.toPoByUpdateDTO(updateDTO);
        this.userInfoService.updateById(userInfo);
        return Result.ok(ResultMsgContact.UPDATE_SUCCESS);
    }

    /**
     * 用户信息状态更改
     *
     * @param updateDTO
     * @return
     */
    @PutMapping("/update_static")
    @ApiOperation("用户信息状态更改")
    @PreventRepeatSubmit
    @OperateLog(title = "用户信息状态更改", type = OperateType.UPDATE)
    public Result<String> updateUserInfoStatic(@RequestBody UpdateStatusDTO updateDTO) {
        //必要字段校验
        if (BeanUtil.isEmpty(updateDTO)) {
            throw new DataException(ResultCodeEnum.DATA_LACK);
        }
        // 状态数字合法性校验
        if (!InputDataUtil.numIsOK(updateDTO.getStatus())) {
            throw new DataException(ResultCodeEnum.TYPE_NUM_ERR);
        }
        //转换数据
        UserInfo userInfo = this.userInfoConverter.toPoByUpdateStaticDTO(updateDTO);
        this.userInfoService.updateById(userInfo);
        return Result.ok(ResultMsgContact.UPDATE_SUCCESS);
    }

    /**
     * 用户信息个人密码修改
     *
     * @param updateDTO
     * @return
     */
    @PutMapping("/update_pwd")
    @ApiOperation("用户信息个人密码修改")
    @PreventRepeatSubmit
    @OperateLog(title = "用户信息个人密码修改", type = OperateType.UPDATE)
    public Result<String> updateUserInfoSelfPwd(@RequestBody UpdatePasswordDTO updateDTO) {
        //校验密码
        PasswordUtil.validate(updateDTO);
        //判断账号是否一致
        UserInfo userInfo = this.userInfoService.getOne(new QueryWrapper<UserInfo>().select("password").eq("id", updateDTO.getId()));
        if (ObjectUtil.isNull(userInfo)) {
            throw new ServiceException(ResultCodeEnum.USERNAME_IS_NOT_EXIT);
        }
        //判断输入的旧密码与密码是否一致
        if (PasswordUtil.isNotEqual(userInfo.getPassword(), updateDTO.getOldPassword())) {
            throw new DataException(ResultCodeEnum.OLD_PASSWORD_NOT_WITH);
        }
        //转换数据
        UserInfo save = this.userInfoConverter.toPoByUpdatePasswordDTO(updateDTO);
        //保存数据
        this.userInfoService.updateById(save);
        return Result.ok(ResultMsgContact.UPDATE_SUCCESS);
    }


    /**
     * 用户信息分页搜索
     */
    @GetMapping("/getPage")
    @ApiOperation("用户信息分页搜索")
    public Result<PageResult<UserInfoVO>> queryUserInfoPage(PageDTO pageDTO) {
        //必要字段校验
        if (ObjectUtil.hasNull(pageDTO.getPageSize(), pageDTO.getPageNum())) {
            throw new DataException(ResultCodeEnum.DATA_LACK);
        }
        //查询数据
        PageResult<UserInfoVO> result = this.userInfoService.selectPage(pageDTO);
        return Result.ok(result);
    }

    /**
     * 根据用户ID获取用户详情
     */
    @GetMapping("/getUserDetailInfo/{userId}")
    @ApiOperation("根据用户ID获取用户详情")
    public Result<UserInfoVO> getUserDetailInfo(@PathVariable Long userId) {
        //根据用户ID查询用户信息。正常使用的
        UserInfo one = this.userInfoService.getOne(new LambdaQueryWrapper<UserInfo>()
                .eq(UserInfo::getId, userId)
                .eq(UserInfo::getStatus, SqlColumnConstant.STATUS_OK)
        );
        if (ObjectUtil.isNull(one)) {
            throw new ServiceException(ResultCodeEnum.USER_IS_NOT_EXIT);
        }
        // 设置完整路径
        if (StrUtil.isNotBlank(one.getAvatar())) {
            one.setAvatar(ossConfig.getUrl() + one.getAvatar());
        }
        return Result.ok(this.userInfoConverter.toVo(one));
    }
}
